function qvTrace(varargin)
% qvTrace
%
% Use this to look at nimex ephus xsg traces.
%   Derived from quickViewTrace.
%
% If called with no input argument, or 'init', it will go to the
%   default directory (specified below) and ask you to select
%   a file. If called with 'init' and and valide path name as 
%   arguments, it will go to that directory before prompting.
%
% Example: qvTrace('init', 'C:\_Data')
%
% Notes:
%   Data are available as 'currentTrace' variable in the workspace

% TODO:
%   Option to hold display to accumulate traces

% editing:
% gs dec 2007 -- Adapted from quickViewTrace
% ----------------------------------------------------

defaultDirectory = 'C:\_Data';

if nargin == 0 || strcmp(varargin{1}, 'init')
    mode = 'init';
    if nargin < 2
    elseif nargin >1 && ~isempty(varargin{2})
        defaultDirectory = varargin{2};
    end
else
    mode = varargin{1};
end

switch mode
    case 'init'
        data = [];
        try
            cd(defaultDirectory);
        catch
            try
                cd('C:\Data');
            catch
%                 disp('qvTrace: unable to find default dir.')
            end
        end
        [filename, pathname] = uigetfile('*.xsg', 'Select an XSG trace');
        if isequal(filename,0) || isequal(pathname,0)
            return
        end
        fullfilename = fullfile(pathname, filename);
        [pathstr, tracename, ext, versn] = fileparts(fullfilename);
        data.completename = fullfile(pathstr, [tracename, ext, versn]);
        data.hfig = figure;
        set(data.hfig, 'Color', 'w', 'Name', 'qvTrace', ...
            'NumberTitle', 'off', 'Position', [360    55   560   657]);
    case 'select new file'
        data = get(gcf, 'UserData');
        saveCurrentDirectory = pwd;
        pathstr = fileparts(data.completename);
        cd(pathstr);
        [filename, pathname] = uigetfile('*.xsg', 'Select an XSG trace');
        if isequal(filename,0) || isequal(pathname,0)
            return
        end
        fullfilename = fullfile(pathname, filename);
        [pathstr, tracename, ext, versn] = fileparts(fullfilename);
        data.completename = fullfile(pathstr, [tracename, ext, versn]);
        cd(saveCurrentDirectory)
        clf;
    case 'scroll backwards'
        data = get(gcf, 'UserData');
        clf;
        [pathstr, tracename, ext] = fileparts(data.completename);
        fullfile(pathstr, ['*' ext]);
        traceFiles = dir(fullfile(pathstr, ['*' ext]));
        c = struct2cell(traceFiles);
        list = char(c{1,:});
        k = strmatch(tracename, list);
        if k > 1
            newfilename = list(k-1,:); % file name of the preceding (k-1) file
            data.completename = fullfile(pathstr, newfilename);
            [pathstr, tracename] = fileparts(data.completename);
        end
    case 'scroll forwards'
        data = get(gcf, 'UserData');
        clf;
        [pathstr, tracename, ext] = fileparts(data.completename);
        fullfile(pathstr, ['*' ext]);
        traceFiles = dir(fullfile(pathstr, ['*' ext]));
        c = struct2cell(traceFiles);
        list = char(c{1,:});
        k = strmatch(tracename, list);
        if k < size(list, 1)
            newfilename = list(k+1,:); % file name of the following (k+1) file
            data.completename = fullfile(pathstr, newfilename);
            [pathstr, tracename] = fileparts(data.completename);
        end
end
set(data.hfig, 'UserData', data);

% open the file, extract the data
currentTrace = load(data.completename, '-mat');
currentTrace.userFcn.filename = data.completename;

% put the data in the workspace
assignin('base', 'currentTrace', currentTrace);

% store in figure's userData
data.currentTrace = currentTrace;
set(data.hfig, 'UserData', data);

% TODO: fix this temporary KLUGE
if ~isfield(currentTrace.header.acquirer.acquirer, 'acqOnArray')
    currentTrace.header.acquirer.acquirer.acqOnArray = 0;
end

% determine what was acq'd and stim'd, and how
NacqEphys = currentTrace.header.ephys.ephys.startButton * ...
    sum(currentTrace.header.ephys.ephys.acqOnArray);
Nother = currentTrace.header.ephys.ephys.startButton * ...
    sum(currentTrace.header.ephys.ephys.stimOnArray) + ...
    currentTrace.header.acquirer.acquirer.startButton * ...
    sum(currentTrace.header.acquirer.acquirer.acqOnArray) + ...
    currentTrace.header.stimulator.stimulator.startButton * ...
    sum(currentTrace.header.stimulator.stimulator.stimOnArray);

% decide subplot layout
Nsub = 2 * NacqEphys + Nother; % ephys traces count double
plotnum = 0;

% were data obtained by pulseJacker? (If so, different method for determining pulses)
pulseJackerFlag = currentTrace.header.pulseJacker.pulseJacker.enable; 
if pulseJackerFlag; 
    disp(' '); 
    disp('pulseJacker trace'); 
end

% who triggered whom:
disp(' ');
disp(['ephys startButton: ' num2str(currentTrace.header.ephys.ephys.startButton)]);
disp(['acq startButton: ' num2str(currentTrace.header.acquirer.acquirer.startButton)]);
disp(['stim startButton: ' num2str(currentTrace.header.stimulator.stimulator.startButton)]);
disp(['ephys externalTrigger: ' num2str(currentTrace.header.ephys.ephys.externalTrigger)]);
disp(['acq externalTrigger: ' num2str(currentTrace.header.acquirer.acquirer.externalTrigger)]);
disp(['stim externalTrigger: ' num2str(currentTrace.header.stimulator.stimulator.externalTrigger)]);

% loop??: yes, if selfTrigger=0 for all started programs (startButton=1)
loopFlag = 0;
loopDaqFlag = 0;
loopCpuFlag = 0;
loopIterations = currentTrace.header.loopGui.loopGui.iterations;
loopIterationCounter = currentTrace.header.loopGui.loopGui.iterationCounter;
numberOfSelfTriggeringPrograms = currentTrace.header.ephys.ephys.startButton * currentTrace.header.ephys.ephys.selfTrigger + ...
currentTrace.header.acquirer.acquirer.startButton * currentTrace.header.acquirer.acquirer.selfTrigger + ...
currentTrace.header.stimulator.stimulator.startButton * currentTrace.header.stimulator.stimulator.selfTrigger;
if numberOfSelfTriggeringPrograms == 0
    loopFlag = 1;
    if currentTrace.header.loopGui.loopGui.cpuTiming
        loopCpuFlag = 1; 
        loopDaqFlag = 0;
    else
        loopCpuFlag = 0; 
        loopDaqFlag = 1;
    end
    loopIterations = currentTrace.header.loopGui.loopGui.iterations;
end
disp(['loopFlag: ' num2str(loopFlag) '; loopCpuFlag: ' num2str(loopCpuFlag) '; loopDaqFlag: ' num2str(loopDaqFlag) ...
    '; iterations: ' num2str(loopIterations) '; counter: ' num2str(loopIterationCounter)]);

currentTrace.userFcn.fIAnalysis.familyType = '';
% ============ EPHYS TRACE, CHANNEL 1 ==================
% TODO: plot multiple channels using FOR loop
if currentTrace.header.ephys.ephys.startButton && currentTrace.header.ephys.ephys.acqOnArray(1) == 1;
    ephysdata = currentTrace.data.ephys.trace_1;
    timedata = 0 : size(ephysdata, 1) - 1;
    timedata = timedata / currentTrace.header.ephys.ephys.sampleRate;
    plotnum = plotnum + 1;
    subplot(Nsub, 1, [plotnum plotnum+1]);
    plotnum = plotnum + 1; % double-high subplot for ephys traces
    plot(timedata, ephysdata);
    xlabel('Time (seconds)');
    ylabel('Amplitude');
    traceType = '';
    if loopFlag
        if loopCpuFlag
            traceType = [' -- cpu loop, iteration ' ...
                num2str(loopIterationCounter) ' of ' num2str(loopIterations)];
            currentTrace.userFcn.fIAnalysis.familyType = 'cpu loop';
        elseif loopDaqFlag
            traceType = [' -- daq loop, all ' num2str(loopIterations) ' iterations'];
            currentTrace.userFcn.fIAnalysis.familyType = 'daq loop';
        end
    else
        currentTrace.userFcn.fIAnalysis.familyType = 'not a loop';
    end
    htitle = title([pathstr '\' tracename traceType]);
    set(htitle, 'Interpreter', 'none');
    box off;
    axis tight
end

% plot corresponding ephys stim pulse
% TODO: determine timedata here, instead of relying on the above
if currentTrace.header.ephys.ephys.startButton && currentTrace.header.ephys.ephys.stimOnArray(1) == 1;
    try % TODO: get rid of the try 
        traceLength = currentTrace.header.ephys.ephys.traceLength;
        if ~pulseJackerFlag
            params = currentTrace.header.ephys.ephys.pulseParameters{:};
            if isempty(params)
                try
                    params = currentTrace.header.ephys.ephys.pulseParameters{2}; % probably wrong for 2nd chan
                catch
                    disp('qvTrace: field pulseParameters is empty.')
                end
            end
            % here's where the problem is. if there's only one amp channel,
            % there's only one index. but if there are two channels, the
            % first channel's pulse has index 2; index 1 is empty.
        else
            % TODO: check this stuff ...
            cp = currentTrace.header.pulseJacker.pulseJacker.currentPosition;
            np = size(currentTrace.header.pulseJacker.pulseJacker.positions{1}, 2);
            params = currentTrace.header.pulseJacker.pulseJacker.pulseDataMap{(cp-1)*np+1}(:);
        end
        pulseTrace = pulseTraceFromParameters(params, traceLength);
        timedata = ((0 : currentTrace.header.ephys.ephys.sampleRate * currentTrace.header.ephys.ephys.traceLength - 1) / ...
            currentTrace.header.ephys.ephys.sampleRate)';
        if loopFlag && loopDaqFlag
            pulseTrace = repmat(pulseTrace, loopIterations, 1);
            timedata = ((0 : currentTrace.header.ephys.ephys.sampleRate * currentTrace.header.ephys.ephys.traceLength ...
                * loopIterations - 1) / currentTrace.header.ephys.ephys.sampleRate)';
        end
        plotnum = plotnum + 1;
        subplot(Nsub, 1, plotnum);
        hplot = plot(timedata, pulseTrace);
        set(hplot, 'LineWidth', 2, 'Color', 'r');
        xlabel('Time (seconds)');
        ylabel('Amplitude');
        htitle = title(['Pulse: ' params.name]);
        set(htitle, 'Interpreter', 'none');
        box off;
        axis tight
    catch
        disp('qvTrace: problem making ephys stim pulse.')
    end
end

% update the data in the workspace
assignin('base', 'currentTrace', currentTrace);

% store in figure's userData
data.currentTrace = currentTrace;
set(data.hfig, 'UserData', data);

% % ============ ACQUIRER TRACE(S) ==================
% % TODO: plot multiple acquirer traces using FOR loop
if currentTrace.header.acquirer.acquirer.startButton && ...
        currentTrace.header.acquirer.acquirer.acqOnArray(1) == 1;
    acquirerdata = currentTrace.data.acquirer.trace_1;
    timedata = 0 : size(acquirerdata, 1) - 1;
    sr = currentTrace.header.acquirer.acquirer.sampleRate;
    timedata = timedata / sr;
    plotnum = plotnum + 1;
    hsub = subplot(Nsub, 1, plotnum);
    hplot = plot(timedata, acquirerdata);
    xlabel('Time (seconds)');
    ylabel('Amplitude');
%     htitle = title([pathstr '\' tracename]);
%     set(htitle, 'Interpreter', 'none');
    box off;
    axis tight
end

% % ============ STIMULATOR TRACE(S) ==================
% % TODO: plot multiple stimulator traces using FOR loop
% % TODO: get this working for flashes! (or make a qvFlash)
% if currentTrace.header.stimulator.stimulator.startButton && currentTrace.header.stimulator.stimulator.stimOnArray(1) == 1;
%     params = currentTrace.header.stimulator.stimulator.pulseParameters{:};
%     traceLength = currentTrace.header.stimulator.stimulator.traceLength;
%     if ~pulseJackerFlag
%         params = currentTrace.header.stimulator.stimulator.pulseParameters{:};
%     else
%         cp = currentTrace.header.pulseJacker.pulseJacker.currentPosition;
%         np = size(currentTrace.header.pulseJacker.pulseJacker.positions{1})
%         params = currentTrace.header.pulseJacker.pulseJacker.pulseDataMap{(cp-1)*np+1}(:);
%     end
%     pulseTrace = pulseTraceFromParameters(params, traceLength);
%     plotnum = plotnum + 1;
%     hsub = subplot(Nsub, 1, plotnum);
%     hplot = plot(timedata, pulseTrace);
%     set(hplot, 'LineWidth', 2, 'Color', 'r');
%     xlabel('Time (seconds)');
%     ylabel('Amplitude');
%     htitle = title(['Pulse: ' params.name]);
%     set(htitle, 'Interpreter', 'none');
%     box off;
% end

% menu additions
addMenuToFigure(gcf, 'UserFcns', ...
    'Label', 'Calculate cell parameters from negative V step', ...
    'Callback', 'calcCellParamsFromNegVstep', ...
    'Label', 'Show family of traces', ...
    'Callback', 'showFamilyOfTraces', ...
    'Label', 'Frequency-current (f-I) analysis', ...
    'Callback', 'frequencyCurrentAnalysis');
addMenuToFigure(gcf, 'autoNotes', ...
    'Label', 'show autoNotes for current experiment', ...
    'callBack', 'showAutoNotesForTrace');

% uicontrols 
uicontrol('Style', 'pushbutton', 'String', '<<', 'Units', 'normalized', ...
    'Position', [.92 .93 .04 .07], 'Callback', 'qvTrace(''scroll backwards'')');
uicontrol('Style', 'pushbutton', 'String', '>>', 'Units', 'normalized', ...
    'Position', [.96 .93 .04 .07], 'Callback', 'qvTrace(''scroll forwards'')');
uicontrol('Style', 'pushbutton', 'String', 'New', 'Units', 'normalized', ...
    'Position', [.92 .86 .08 .07], 'Callback', 'qvTrace(''select new file'')');
uicontrol('Style', 'text', 'String', ...
    ['epoch ' num2str(currentTrace.header.xsg.xsg.epoch)], ...
    'Units', 'normalized', 'Position', [.01 .96 .1 .03]);

